#include "manipulator.h"

#include <gl\glfw.h>
#include "shapes3d.h"

void Manipulator::render()
{
	if( selectedSceneObj )
	{
		x_handle.vRender();
		y_handle.vRender();
		z_handle.vRender();

		x_angular_handle.vRender();
		y_angular_handle.vRender();
		z_angular_handle.vRender();
	}
}


void Manipulator::setSceneObject( SceneObject * sceneObject )
{
	isSelected = false;
	selectedSceneObj = sceneObject;
}

void Manipulator::update(float speed)
{
	if( !selectedSceneObj ) return;
	const Vec3f &pos = selectedSceneObj->vGetPosition();

	x_handle.m_position = pos;
	y_handle.m_position = pos;
	z_handle.m_position = pos;

	x_angular_handle.m_position = pos;
	y_angular_handle.m_position = pos;
	z_angular_handle.m_position = pos;

	float scaledSpeed = speed * 0.05f;
	x_handle.speed = scaledSpeed;
	y_handle.speed = scaledSpeed;
	z_handle.speed = scaledSpeed;

	x_angular_handle.speed = scaledSpeed;
	y_angular_handle.speed = scaledSpeed;
	z_angular_handle.speed = scaledSpeed;
}

void Manipulator::init()
{
	x_handle.axis.is(1,0,0);
	y_handle.axis.is(0,1,0);
	z_handle.axis.is(0,0,1);

	x_angular_handle.axis.is(1,0,0);
	y_angular_handle.axis.is(0,1,0);
	z_angular_handle.axis.is(0,0,1);
}


void AxisHandle::vRender()
{	
	const float length = 2.8f;
	const float half = 1.4f;
	glPushMatrix();
	{
		glTranslatef( m_position.x() + half * axis.z() , m_position.y() - half * axis.y() , m_position.z() - half * axis.x() ); 
		//glMultMatrixf( transform_.v_ );
		glRotatef(90, axis.x(), axis.y(), axis.z() );

		glColor3fv( &axis[0] );
		Shapes3D::DrawCylinder(0.1f, length, 12, true);
	}glPopMatrix();
}

void AxisHandle::vPicking()
{
	scaleMode = false; // TODO deactivate a more logical place...
	const float length = 2.8f;
	const float half = 1.4f;
	glPushMatrix();
	{
		glTranslatef( m_position.x() + half * axis.z() , m_position.y() - half * axis.y() , m_position.z() - half * axis.x() ); 
		//glMultMatrixf( transform_.v_ );
		glRotatef(90, axis.x(), axis.y(), axis.z() );
		glColor3ub(m_colorID[0], m_colorID[1], m_colorID[2]);
		Shapes3D::DrawCylinder(0.1f, length, 12, true);
	}glPopMatrix();
}


void AngleHandle::vRender()
{
	glPushMatrix();
	{
		glTranslatef( m_position.x(), m_position.y(), m_position.z() ); 

		glRotatef(90, axis.x(), axis.y(), axis.z() );
		
		if( axis.x() == 1.0f  ) glColor3f( 1,1,0 );
		if( axis.y() == 1.0f  ) glColor3f( 1,0,1 );
		if( axis.z() == 1.0f  ) glColor3f( 0,1,1 );

		Shapes3D::DrawTorus(0.1f, 1.2f);
	}glPopMatrix();
}

void AngleHandle::vPicking()
{
	glPushMatrix();
	{
		glTranslatef( m_position.x(), m_position.y(), m_position.z() ); 
		glRotatef(90, axis.x(), axis.y(), axis.z() );
		glColor3ub(m_colorID[0], m_colorID[1], m_colorID[2]);
		Shapes3D::DrawTorus(0.1f, 1.2f);
	}glPopMatrix();
}



void AxisHandle::vInteractWith( SceneObject *mutator )
{
	if( !mutator )
	{
		throw ("passed null ptr!");
	}

	if( scaleMode )
	{
		mutator->vScale( axis, speed );
	}else
	{
		mutator->vSetPosition( mutator->vGetPosition() + Vec3f( axis.z(), -axis.y(), axis.x() ) * speed );
	}
	
}

void AngleHandle::vInteractWith( SceneObject *mutator )
{
	if( !mutator ) throw ("passed null ptr!");

	Quatf addedRot = mutator->vGetOrientation();
	addScaledVector( addedRot,  Vec3f( axis.z(), axis.y(), axis.x() ),  speed  ); 
	mutator->vSetOrientation( addedRot );

}

void Manipulator::addHandlesToList( std::list< SceneObject* > &sceneObjects )
{
	sceneObjects.push_back( &x_handle );
	sceneObjects.push_back( &y_handle );
	sceneObjects.push_back( &z_handle );

	sceneObjects.push_back( &x_angular_handle );
	sceneObjects.push_back( &y_angular_handle );
	sceneObjects.push_back( &z_angular_handle );
}

void Manipulator::setScaling( bool scaleActive )
{
	x_handle.scaleMode = scaleActive;
	y_handle.scaleMode = scaleActive;
	z_handle.scaleMode = scaleActive;
}

void Manipulator::activateTool(SceneObject *tool)
{
	selectedTool = tool;
}

void Manipulator::useActiveTool()
{
	if( selectedTool )
		selectedTool->vInteractWith(selectedSceneObj);
}
